//
// Created by hjie on 24-1-9.
//

#pragma once
#include "message_queue.h"
#include "operate_define.h"
#include <vector>
#include <cstdint>
#include <libavcodec/packet.h>
#include <map>
#include <thread>
#include <memory>
#include <vector>

struct OutputFileAndDataInfo;
struct InputFileAndDataInfo;
struct OutputStream;

struct InputStream
{
    std::shared_ptr<InputFileAndDataInfo> m_stream_link_input_file_ctx;
    FrameMessageQueue m_decode_frame_queue;
    std::shared_ptr<MediaStream> m_media_stream;
    int64_t m_now_time{0};
    AVFilterContext * m_filter_buffer;
    int64_t m_duration_of_frame{0};
};

struct InputFileAndDataInfo
{
    InputFormatContext  * m_input_file_ctx{nullptr};
    AVFilterContext     * m_buffer_filter_ctx{nullptr}; // for video filter buffer ctx
    PacketMessageQueue    m_read_packet_queue;
    std::thread           m_read_file_thread;           // read packet data thread
    int			          m_index;
    bool                  m_is_eof;
    int                   m_x;
    int                   m_y;
};

struct OutputStream
{
    std::shared_ptr<OutputFileAndDataInfo> m_stream_link_output_file_ctx;
    std::shared_ptr<MediaStream> m_media_stream;
    int64_t m_now_time{0};
};

struct OutputFileAndDataInfo
{
    bool                  m_output_is_init;
    OutputFormatContext * m_output_file_ctx{nullptr};
    AVFilterContext     * m_filter_sink_ctx{nullptr};
    AVFilterContext     * m_audio_filter_sink_ctx{nullptr};
    std::string           m_output_filename;
    PacketMessageQueue    m_encoder_packet_queue;
    PacketMessageQueue    m_sync_process_packet_queue;
    bool                  m_video_init{false};
    bool                  m_audio_init{false};
    int                   m_index{-1};
    int64_t               m_video_pts{0};
    int64_t               m_audio_pts{0};
};

struct XstackConfig
{
    int m_width;
    int m_height;
    int m_cell_width;
    int m_cell_height;
    int m_framerate;
    std::string m_content;
};

struct XstackFilterDataInfo
{
    AVFilterGraph   * m_filter_graph{nullptr};
    std::map<int, InputFileAndDataInfo*>  m_input_file_map;
    std::shared_ptr<OutputFileAndDataInfo> m_output_file_ctx;
    std::map<int,std::shared_ptr<InputStream>>  m_input_stream_map;
    std::map<int,std::shared_ptr<OutputStream>> m_output_stream_map;
    FrameMessageQueue m_filter_frame_queue;

    XstackConfig m_config;
};

bool InitInputFile(std::vector<std::string> input_file_vec, XstackFilterDataInfo & xstack_data);
bool InitXstackFilter(XstackFilterDataInfo & xstack_filter_data);
bool InitOutputFile(const std::string & m_output_filename, XstackFilterDataInfo & xstack_filter_data, AVFrame * frame);

void ProcessLibX264(XstackFilterDataInfo & xstack_filter_data, AVFrame * frame);

void DumpInputData(XstackFilterDataInfo & xstack_data);


void InitAudioStreamCopyModol(XstackFilterDataInfo & xstack_info);

void PushPacketToQueue(XstackFilterDataInfo & xstack_data, AVPacket * packet);
